﻿using System;
using System.Data;
using System.Web;
using Me.Amon.Da.Db;
using Me.Amon.Da.Db.KPT;
using Me.Amon.Util;
using Newtonsoft.Json;

namespace Me.Amon.KPT
{
    /// <summary>
    /// SKpt 的摘要说明
    /// </summary>
    public class SKpt : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/JSON";

            var obj = new MKpt();

            // 操作
            var opt = context.Request[PKpt.PARAM_KEY_OPT];
            if (string.IsNullOrEmpty(opt))
            {
                obj.error_code = PKpt.ERROR_CODE_OPT_EMPTY;
                context.Response.Write(Serialize(obj));
                context.Response.End();
                return;
            }

            // 用户
            var user = context.Request[PKpt.PARAM_KEY_USER];
            if (!CharUtil.IsValidateHash(user))
            {
                obj.error_code = PKpt.ERROR_CODE_USER_ERROR;
                context.Response.Write(Serialize(obj));
                context.Response.End();
                return;
            }

            var dba = new RDBEngine();

            switch (opt)
            {
                case PKpt.PARAM_OPT_LIST_GTDS:
                    ListGtds(context, user, dba);
                    break;
                case PKpt.PARAM_OPT_DETAIL_GTD:
                    ReadGtd(context, obj, user, dba);
                    break;
                case PKpt.PARAM_OPT_CREATE_GTD:
                    CreateGtd(context, obj, user, dba);
                    break;
                case PKpt.PARAM_OPT_UPDATE_GTD:
                    UpdateGtd(context, obj, user, dba);
                    break;
                case PKpt.PARAM_OPT_CHANGE_GTD:
                    ChangeGtd(context, obj, user, dba);
                    break;
                case PKpt.PARAM_OPT_DELETE_GTD:
                    ChangeGtd(context, obj, user, dba);
                    break;
                case PKpt.PARAM_OPT_UPDATE_KPT:
                    UpdateKpt(context, obj, user, dba);
                    break;
                default:
                    obj.error_code = PKpt.ERROR_CODE_OPT_ERROR;
                    context.Response.Write(JsonConvert.SerializeObject(obj, Formatting.None));
                    break;
            }
            context.Response.End();
        }

        private void ListGtds(HttpContext context, string user, RDBEngine dba)
        {
            var s = context.Request[PKpt.PARAM_DAT_STATUS];
            if (!CharUtil.IsValidateLong(s))
            {
                s = "0";
            }

            dba.AddTable(DKpt.TABLE);
            dba.AddWhere(DKpt.USERID, user);
            dba.AddWhere(DKpt.Status, "=", s, false);
            var m = context.Request[PKpt.PARAM_DAT_MAJOR];
            if (CharUtil.IsValidateLong(m))
            {
                dba.AddWhere(DKpt.Major, "=", m, false);
            }
            var l = context.Request[PKpt.PARAM_DAT_LABEL];
            if (CharUtil.IsValidateLong(l))
            {
                dba.AddWhere(DKpt.Major, "=", l, false);
            }

            var dt = dba.ExecuteSelect();
            int cnt = dt.Rows.Count;
            var gtds = new MKpt[cnt];

            if (cnt > 0)
            {
                int i = 0;
                foreach (DataRow row in dt.Rows)
                {
                    gtds[i++] = ListGtds(row);
                }
            }

            context.Response.Write(Serialize(gtds));
            context.Response.End();
        }

        private void ListGtds(bool major, bool label)
        {
            var dba = new RDBEngine();
            dba.AddTable(DKpt.TABLE);
            dba.AddWhere(DKpt.USERID, "");
            dba.AddWhere(DKpt.Status, "=", CKpt.STATUS_NORMAL);
            dba.AddWhere(DKpt.Major, major);
            dba.AddWhere(DKpt.Label, label);

            var dt = dba.ExecuteSelect();
            int cnt = dt.Rows.Count;
            if (cnt < 1)
            {
                return;
            }

            var gtds = new MKpt[cnt];
            int i = 0;
            foreach (DataRow row in dt.Rows)
            {
                gtds[i++] = ListGtds(row);
            }
        }

        private MKpt ListGtds(DataRow row)
        {
            var gtd = new MKpt();
            gtd.Id = row[DKpt.Id] as string;
            gtd.Order = (int)row[DKpt.ORDER];
            gtd.Major = DKpt.VALUE_TRUE == row[DKpt.Major] as string;
            gtd.Label = DKpt.VALUE_TRUE == row[DKpt.Label] as string;
            gtd.Subject = row[DKpt.Subject] as string;
            gtd.CreateTime = (DateTime)row[DKpt.CreateTime];

            return gtd;
        }

        private void ReadGtd(HttpContext context, MKpt gtd, string user, RDBEngine dba)
        {
            var id = context.Request[PKpt.PARAM_DAT_GTD];
            if (!CharUtil.IsValidateHash(id))
            {
                gtd.error_code = PKpt.ERROR_CODE_KEY_EMPTY;
                context.Response.Write(Serialize(gtd));
                context.Response.End();
                return;
            }

            dba.AddTable(DKpt.TABLE);
            dba.AddWhere(DKpt.USERID, user);
            dba.AddWhere(DKpt.Id, id);

            var dt = dba.ExecuteSelect();
            if (dt.Rows.Count == 1)
            {
                gtd = LoadGtd(dt.Rows[0]);
            }

            context.Response.Write(Serialize(gtd));
            context.Response.End();
        }

        /// <summary>
        /// 创建GTD
        /// </summary>
        /// <param name="context"></param>
        /// <param name="dba"></param>
        private void CreateGtd(HttpContext context, MKpt gtd, string user, RDBEngine dba)
        {
            var ds = context.Request[PKpt.PARAM_DAT_SUBJECT];
            if (string.IsNullOrWhiteSpace(ds))
            {
                gtd.error_code = PKpt.ERROR_CODE_SUBJECT_EMPTY;
                context.Response.Write(Serialize(gtd));
                context.Response.End();
                return;
            }

            gtd.UserId = user;
            gtd.Major = DKpt.VALUE_TRUE == context.Request[PKpt.PARAM_DAT_MAJOR];
            gtd.Label = DKpt.VALUE_TRUE == context.Request[PKpt.PARAM_DAT_LABEL];
            gtd.Subject = ds;
            gtd.Content = context.Request[PKpt.PARAM_DAT_CONTENT] ?? "";
            //gtd.Project = context.Request[PKpt.PARAM_DAT_PROJECT] ?? "0";

            SaveGtd(gtd, dba);
            context.Response.Write(Serialize(gtd));
            context.Response.End();
        }

        /// <summary>
        /// 更新GTD
        /// </summary>
        private void UpdateGtd(HttpContext context, MKpt gtd, string user, RDBEngine dba)
        {
            var id = context.Request[PKpt.PARAM_DAT_GTD];
            if (!CharUtil.IsValidateHash(id))
            {
                return;
            }

            var tx = context.Request[PKpt.PARAM_DAT_SUBJECT];
            if (string.IsNullOrWhiteSpace(tx))
            {
                return;
            }

            dba.AddTable(DKpt.TABLE);
            dba.AddParam(DKpt.Subject, tx);
            dba.AddParam(DKpt.Content, context.Request[PKpt.PARAM_DAT_CONTENT]);
            dba.AddParam(DKpt.Major, DKpt.VALUE_TRUE == context.Request[PKpt.PARAM_DAT_MAJOR]);
            dba.AddParam(DKpt.Label, DKpt.VALUE_TRUE == context.Request[PKpt.PARAM_DAT_LABEL]);
            dba.AddWhere(DKpt.Id, id);
            dba.AddWhere(DKpt.USERID, user);
            dba.ExecuteUpdate();

            SendOK(context, id);
        }

        /// <summary>
        /// 设置KPT
        /// </summary>
        private void UpdateKpt(HttpContext context, MKpt gtd, string user, RDBEngine dba)
        {
            var id = context.Request[PKpt.PARAM_DAT_GTD];
            if (!CharUtil.IsValidateHash(id))
            {
                return;
            }

            dba.AddTable(DKpt.TABLE);

            bool ok = false;
            var txt = context.Request[PKpt.PARAM_DAT_K];
            if (txt != null)
            {
                dba.AddParam(DKpt.Keep, txt);
                ok = true;
            }
            txt = context.Request[PKpt.PARAM_DAT_P];
            if (txt != null)
            {
                dba.AddParam(DKpt.Problem, txt);
                ok = true;
            }
            txt = context.Request[PKpt.PARAM_DAT_T];
            if (txt != null)
            {
                dba.AddParam(DKpt.Try, txt);
                ok = true;
            }

            if (!ok)
            {
                return;
            }

            dba.AddWhere(DKpt.Id, id);
            dba.AddWhere(DKpt.USERID, user);
            dba.ExecuteUpdate();

            SendOK(context, txt);
        }

        /// <summary>
        /// 更新TAG
        /// </summary>
        private void UpdateTag(HttpContext context, MKpt gtd, string user, RDBEngine dba)
        {
        }

        private void ChangeGtd(HttpContext context, MKpt gtd, string user, RDBEngine dba)
        {
            var id = context.Request[PKpt.PARAM_DAT_GTD];
            if (!CharUtil.IsValidateHash(id))
            {
                return;
            }

            bool ok = false;
            var st = context.Request[PKpt.PARAM_DAT_STATUS];
            if (CharUtil.IsValidateLong(st))
            {
                dba.AddParam(DKpt.Status, st);
                ok = true;
            }
            var sm = context.Request[PKpt.PARAM_DAT_MAJOR];
            if (CharUtil.IsValidateLong(sm))
            {
                dba.AddParam(DKpt.Major, sm == "1");
                ok = true;
            }
            var sl = context.Request[PKpt.PARAM_DAT_LABEL];
            if (CharUtil.IsValidateLong(sl))
            {
                dba.AddParam(DKpt.Label, sl == "1");
                ok = true;
            }
            if (!ok)
            {
                return;
            }

            dba.AddTable(DKpt.TABLE);
            dba.AddWhere(DKpt.Id, id);
            dba.AddWhere(DKpt.USERID, user);
            dba.ExecuteUpdate();

            SendOK(context, id);
        }

        #region 私有函数
        private static string Serialize(object obj)
        {
            return JsonConvert.SerializeObject(obj, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
        }

        private void SendOK(HttpContext context, string id)
        {
            context.Response.Write("{\"Id\":\"" + id + "\"}");
            context.Response.End();
        }

        private MKpt LoadGtd(DataRow row)
        {
            var gtd = new MKpt();
            gtd.Id = row[DKpt.Id] as string;
            gtd.Order = (int)row[DKpt.ORDER];
            gtd.Major = DKpt.VALUE_TRUE == row[DKpt.Major] as string;
            gtd.Label = DKpt.VALUE_TRUE == row[DKpt.Label] as string;
            gtd.Subject = row[DKpt.Subject] as string;
            gtd.Content = row[DKpt.Content] as string;
            //gtd.Project = row[DKpt.Project] as string;
            //gtd.Priority = (int)row[DKpt.Priority];
            //gtd.Status = (int)row[DKpt.Status];
            //gtd.Percent = (int)row[DKpt.Percent];
            //gtd.StartTime = (DateTime)row[DKpt.StartTime];
            //gtd.Method = (int)row[DKpt.Method];

            //gtd.EndType = (int)row[DKpt.EndType];
            //gtd.ExeCount = (int)row[DKpt.ExeCount];
            //gtd.EndTime = (DateTime)row[DKpt.EndTime];
            //gtd.LastTime = (DateTime)row[DKpt.LastTime];

            //gtd.Notice = (int)row[DKpt.Notice];
            //gtd.Command = row[DKpt.Command] as string;
            //gtd.Params = row[DKpt.Params] as string;

            //gtd.Shared = DKpt.VALUE_TRUE == row[DKpt.Shared];
            //gtd.SupGtd = row[DKpt.SupGtd] as string;
            //gtd.PreGtd = row[DKpt.PreGtd] as string;
            //gtd.RefId = row[DKpt.RefId] as string;

            gtd.K = row[DKpt.Keep] as string;
            gtd.P = row[DKpt.Problem] as string;
            gtd.T = row[DKpt.Try] as string;

            gtd.CreateTime = (DateTime)row[DKpt.CreateTime];
            gtd.UpdateTime = (DateTime)row[DKpt.UpdateTime];

            return gtd;
        }

        private void SaveGtd(MKpt gtd, RDBEngine dba)
        {
            dba.AddTable(DKpt.TABLE);
            dba.AddParam(DKpt.ORDER, gtd.Order);
            dba.AddParam(DKpt.Major, gtd.Major);
            dba.AddParam(DKpt.Label, gtd.Label);
            dba.AddParam(DKpt.Subject, gtd.Subject);
            dba.AddParam(DKpt.Content, gtd.Content);
            //dba.AddParam(DKpt.Project, gtd.Project);
            //dba.AddParam(DKpt.Priority, gtd.Priority);
            //dba.AddParam(DKpt.Status, gtd.Status);
            //dba.AddParam(DKpt.Percent, gtd.Percent);
            //dba.AddParam(DKpt.StartTime, gtd.StartTime.ToString(IEnv.DATEIME_FORMAT));
            //dba.AddParam(DKpt.Method, gtd.Method);

            //dba.AddParam(DKpt.EndType, gtd.EndType);
            //dba.AddParam(DKpt.ExeCount, gtd.ExeCount);
            //dba.AddParam(DKpt.EndTime, gtd.EndTime.ToString(IEnv.DATEIME_FORMAT));
            //dba.AddParam(DKpt.LastTime, gtd.LastTime.ToString(IEnv.DATEIME_FORMAT));

            //dba.AddParam(DKpt.Notice, gtd.Notice);
            //dba.AddParam(DKpt.Command, gtd.Command);
            //dba.AddParam(DKpt.Params, gtd.Params);

            //dba.AddParam(DKpt.Shared, gtd.Shared);
            //dba.AddParam(DKpt.SupGtd, gtd.SupGtd);
            //dba.AddParam(DKpt.PreGtd, gtd.PreGtd);
            //dba.AddParam(DKpt.RefId, gtd.RefId);

            dba.AddParam(DKpt.Keep, gtd.K);
            dba.AddParam(DKpt.Problem, gtd.P);
            dba.AddParam(DKpt.Try, gtd.T);
            dba.AddParam(DKpt.Status, gtd.Status);

            var now = DateTime.Now;
            if (CharUtil.IsValidateHash(gtd.Id))
            {
                //dba.AddParam(DKpt.CreateTime, DKpt.NOW, false);
                gtd.UpdateTime = now;
                dba.AddParam(DKpt.UpdateTime, now.ToString(IEnv.DATEIME_FORMAT));

                dba.AddWhere(DKpt.Id, gtd.Id);
                dba.AddWhere(DKpt.USERID, gtd.UserId);

                dba.ExecuteUpdate();
            }
            else
            {
                gtd.Id = HashUtil.UtcTimeInHex();

                gtd.CreateTime = now;
                gtd.UpdateTime = now;
                dba.AddParam(DKpt.CreateTime, now.ToString(IEnv.DATEIME_FORMAT));
                dba.AddParam(DKpt.UpdateTime, now.ToString(IEnv.DATEIME_FORMAT));

                dba.AddParam(DKpt.Id, gtd.Id);
                dba.AddParam(DKpt.USERID, gtd.UserId);

                dba.ExecuteInsert();
            }
        }
        #endregion

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}